#include "debug.h"
#include "uid.h"

#include "uid_stack.h"

typedef struct stack_item stack_item_t ;

static uidstack_t released = INITIALISE_STATIC_EMPTY_UID_STACK;
static uidstack_t reserved = INITIALISE_STATIC_EMPTY_UID_STACK;

static uid_t uid_current = 0 ;

uid_t uidGenerateSingle () {
  
    if(!isEmptyUIDStack(released))
    { // If there are any released UIDs, use them first
        uid_t id;
        released = popUID(&id, released);
        return id;
    }

    if (++uid_current > 0)
        return uid_current ;
    
    TRACE("System is out of unique ID's!") ;
    return UID_EMPTY ;
}


void uidReleaseSingle (uid_t uid) {
    if (uid <= 0) { 
      TRACE ("Cannot release UID(%li)!", (signed long int) uid) ;
        return ;
    }

    released = pushUID(uid, released);
}

void uidLockSingle (uid_t uid) {
  if(linearSearchUID(uid, reserved))
    {
      TRACE("UID(%li) is already locked!", uid);
      return;
    }

  reserved = pushUID(uid, reserved);
}

void uidUnLockSingle (uid_t uid) {
  reserved = linearRemoveUID(uid, reserved);
}

void uidGenerate (uid_t * ids,size_t count) {
    uid_t * ids_end = ids + count ;
    for (;ids != ids_end;++ids)
        *ids = uidGenerateSingle () ;
}

void uidRelease (uid_t const * ids,size_t count) {
    uid_t const * ids_end = ids + count ;
    for (;ids != ids_end;++ids)
        uidReleaseSingle (*ids) ;
}

void uidLock (uid_t const * ids,size_t count) {
    uid_t const * ids_end = ids + count ;
    for (;ids != ids_end;++ids)
        uidLockSingle (*ids) ;
}

void uidUnLock (uid_t const * ids,size_t count) {
    uid_t const * ids_end = ids + count ;
    for (;ids != ids_end;++ids)
        uidUnLockSingle (*ids) ;
}
